//------------------------------------------------------------------------------
// The confidential and proprietary information contained in this file may
// only be used by a person authorised under and to the extent permitted
// by a subsisting licensing agreement from ARM Limited.
//
//            (C) COPYRIGHT 2012 ARM Limited.
//                ALL RIGHTS RESERVED
//
// This entire notice must be reproduced on all copies of this file
// and copies of this file may only be made by a person if such person is
// permitted to do so under the terms of a subsisting license agreement
// from ARM Limited.
//------------------------------------------------------------------------------
//  Version and Release Control Information:
//
//  File Revision       : 134319
//
//  Date                :  2012-07-27 14:43:09 +0100 (Fri, 27 Jul 2012)
//
//  Release Information : PL401-r0p1-00eac0
//
//------------------------------------------------------------------------------
//  File Purpose        : Transaction tracker to maintain status of
//                        outstanding transcations for a slave interface
//                        and to ensure that no cyclic dependency deadlocks
//                        can occur.
//   
//  Key Configuration Details-
//      - No CDAS 
//      - Acceptance capability 1
//      - Number of connected master interfaces 9
//   
// Notes on port naming conventions- 
//
//     All AXI point to point connections can be considered a 
//     MasterInterface - SlaveInterface connection. 
//
//     The AXI ports on the NIC400 A3BM are named as follows-  
//
//     *_m<n> suffix to denote a MasterInterface (connect to external AXI slave)
//     *_s0 suffix to denote the SlaveInterface  (connect to external AXI master) 
//
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Module Declaration
//------------------------------------------------------------------------------


module nic400_switch2_wr_st_tt_s0_ysyx_rv32
  (
    aw_enable,
    tt_enable,
    wr_enable,
    asel,
    aready,
    wvalid,
    wready,
    wlast,
    resp_valid,
    resp_ready,

    // Miscelaneous connections
    aclk,
    aresetn
  );

  // ---------------------------------------------------------------------------
  //  parameters
  // ---------------------------------------------------------------------------

  // ---------------------------------------------------------------------------
  //  Port definitions
  // ---------------------------------------------------------------------------
    output [8:0] aw_enable;     // address channel enable 
    output [8:0] tt_enable;     // Enable for the selected return channel
    output [8:0] wr_enable;     // Enable for the selected write channel
    input  [8:0] asel;     // Selected address channel
    input        aready;     // add channel response
    input        wvalid;     // request
    input        wready;     // response
    input        wlast;     // last flag
    // Slave Interface Buffered response handshake signals
    input        resp_valid; 
    input        resp_ready;
    // Miscelaneous connections
    input        aclk;
    input        aresetn;


  //----------------------------------------------------------------------------
  // Wires 
  //----------------------------------------------------------------------------



  wire  [8:0]    next_tt_reg;   // next selected master interface
  wire  [8:0]    int_tt_en;   // Enable for the selected return channel
  wire           asel_mask;   //  Tracker push mask

  wire           add_push;           // Detection of AW tracker push
  wire           next_resp_stall;    // next resp stall to ensure sticky valid

  //----------------------------------------------------------------------------
  // Registers 
  //----------------------------------------------------------------------------


  reg          valid_add;   // Last beat not received for the current write
  reg   [8:0]    tt_reg;   // Selected master interface
  reg            resp_stall;   // resp stall to ensure sticky valid
  reg            asel_reg;   // registered incomingdestination
  reg            aready_reg;   // registered aready

  reg   [8:0]    reg_tt_en;     // Enable for the selected return channel

  // ---------------------------------------------------------------------------
  //  start of code
  // ---------------------------------------------------------------------------

   //----------------------- Write address push detection ----------------------
   assign asel_mask = |asel;
   // Register incoming add select a_sel and aready_m from master i/f to
   // enable detection of a new address push
   always @(posedge aclk or negedge aresetn)
     begin : p_add_push_seq
       if (!aresetn)
         begin
             asel_reg  <= 1'b0;
             aready_reg <= 1'b0;
         end
       else
         begin
            if (asel_mask || asel_reg)
             begin
                 asel_reg  <= asel_mask;
             end
            if (aready_reg || aready)
             begin
                aready_reg   <= aready;
             end
         end
     end // p_add_push_seq

   // Detect new address push ensuring no dependency on the aready_m 
   // completion of the address transaction
   assign add_push = ((asel_mask & ~asel_reg) | (asel_mask & asel_reg & aready_reg));


 //---------------------------- Combinatorial logic --------------------------
  // Determine next selected destination
   assign next_tt_reg = add_push ? asel 
                        : (resp_valid && resp_ready) ? {9{1'b0}}
                        : tt_reg;

  //---------------------------- Sequential logic -----------------------------

   always @(posedge aclk or negedge aresetn)
     begin : p_tt_seq
       if (!aresetn) 
         begin
                tt_reg <= {9{1'b0}};
         end
       else if ((add_push) || (resp_valid && resp_ready))
         begin
                tt_reg <= next_tt_reg;
         end
     end // p_tt_seq

  always @(posedge aclk or negedge aresetn)
     begin : p_va_seq
       if (!aresetn) 
         begin
                valid_add <= 1'b0;
         end
       else
         begin
           if (add_push)
                valid_add <= 1'b1;
           if (wvalid && wready && wlast)
                valid_add <= 1'b0;
         end
     end // p_va_seq

  //---------------------------- Output Enables -------------------------------

   assign next_resp_stall = (resp_valid & ~resp_ready);

   always @(posedge aclk or negedge aresetn)
     begin : p_stall_seq
       if (!aresetn)
         begin
          resp_stall <= 1'b0;
        end
       else
         begin
          resp_stall <= next_resp_stall;
        end
     end // p_stall_seq

   
   assign aw_enable = asel;

   assign wr_enable = tt_reg & {9{valid_add}};
   assign int_tt_en = tt_reg;


    always @(posedge aclk or negedge aresetn)
     begin : p_tt_en_seq
       if (!aresetn)
         begin
          reg_tt_en <= {9{1'b0}};
        end
       else if (next_resp_stall && !resp_stall)
         begin
          reg_tt_en <= int_tt_en;
        end
     end // p_tt_en_seq
 
   assign tt_enable = resp_stall ? reg_tt_en : int_tt_en;

//------------------------------------------------------------------------------
// OVL Assertions
//------------------------------------------------------------------------------
// synopsys translate_off

`ifdef ARM_ASSERT_ON



`endif 
// synopsys translate_on

  endmodule

//  --=============================== End ====================================--
